package com.easychat.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.annotation.Resource;

import com.easychat.constants.Constants;
import com.easychat.entity.dto.MessageSendDTO;
import com.easychat.entity.dto.SysSettingDTO;
import com.easychat.entity.dto.TokenUserInfoDTO;
import com.easychat.entity.dto.UserContactSearchResultDTO;
import com.easychat.entity.enums.*;
import com.easychat.entity.po.*;
import com.easychat.entity.query.*;
import com.easychat.exception.BusinessException;
import com.easychat.mappers.*;
import com.easychat.redis.RedisComponent;
import com.easychat.service.UserContactApplyService;
import com.easychat.websocket.MessageHandler;
import org.springframework.stereotype.Service;

import com.easychat.entity.vo.PaginationResultVO;
import com.easychat.service.UserContactService;
import com.easychat.utils.StringTools;
import org.springframework.transaction.annotation.Transactional;


/**
 * 联系人 业务接口实现
 */
@Service("userContactService")
public class UserContactServiceImpl implements UserContactService {

	@Resource
	private UserContactMapper<UserContact, UserContactQuery> userContactMapper;
	@Resource
	private UserInfoMapper<UserInfo, UserInfoQuery> userInfoMapper;
	@Resource
	private GroupInfoMapper<GroupInfo, GroupInfoQuery> groupInfoMapper;
	@Resource
	private UserContactApplyMapper<UserContactApply, UserContactApplyQuery> userContactApplyMapper;
	@Resource
	private ChatSessionMapper<ChatSession, ChatSessionQuery> chatSessionMapper;
	@Resource
	private ChatSessionUserMapper<ChatSessionUser, ChatSessionUserQuery> chatSessionUserMapper;
	@Resource
	private ChatMessageMapper<ChatMessage, ChatMessageQuery> chatMessageMapper;
	@Resource
	private UserContactApplyService userContactApplyService;
	@Resource
	private RedisComponent redisComponent;
	@Resource
	private MessageHandler messageHandler;

	/**
	 * 根据条件查询列表
	 */
	@Override
	public List<UserContact> findListByParam(UserContactQuery param) {
		return this.userContactMapper.selectList(param);
	}

	/**
	 * 根据条件查询列表
	 */
	@Override
	public Integer findCountByParam(UserContactQuery param) {
		return this.userContactMapper.selectCount(param);
	}

	/**
	 * 分页查询方法
	 */
	@Override
	public PaginationResultVO<UserContact> findListByPage(UserContactQuery param) {
		int count = this.findCountByParam(param);
		int pageSize = param.getPageSize() == null ? PageSize.SIZE15.getSize() : param.getPageSize();

		SimplePage page = new SimplePage(param.getPageNo(), count, pageSize);
		param.setSimplePage(page);
		List<UserContact> list = this.findListByParam(param);
		PaginationResultVO<UserContact> result = new PaginationResultVO(count, page.getPageSize(), page.getPageNo(), page.getPageTotal(), list);
		return result;
	}

	/**
	 * 新增
	 */
	@Override
	public Integer add(UserContact bean) {
		return this.userContactMapper.insert(bean);
	}

	/**
	 * 批量新增
	 */
	@Override
	public Integer addBatch(List<UserContact> listBean) {
		if (listBean == null || listBean.isEmpty()) {
			return 0;
		}
		return this.userContactMapper.insertBatch(listBean);
	}

	/**
	 * 批量新增或者修改
	 */
	@Override
	public Integer addOrUpdateBatch(List<UserContact> listBean) {
		if (listBean == null || listBean.isEmpty()) {
			return 0;
		}
		return this.userContactMapper.insertOrUpdateBatch(listBean);
	}

	/**
	 * 多条件更新
	 */
	@Override
	public Integer updateByParam(UserContact bean, UserContactQuery param) {
		StringTools.checkParam(param);
		return this.userContactMapper.updateByParam(bean, param);
	}

	/**
	 * 多条件删除
	 */
	@Override
	public Integer deleteByParam(UserContactQuery param) {
		StringTools.checkParam(param);
		return this.userContactMapper.deleteByParam(param);
	}

	/**
	 * 根据UserIdAndContactId获取对象
	 */
	@Override
	public UserContact getUserContactByUserIdAndContactId(String userId, String contactId) {
		return this.userContactMapper.selectByUserIdAndContactId(userId, contactId);
	}

	/**
	 * 根据UserIdAndContactId修改
	 */
	@Override
	public Integer updateUserContactByUserIdAndContactId(UserContact bean, String userId, String contactId) {
		return this.userContactMapper.updateByUserIdAndContactId(bean, userId, contactId);
	}

	/**
	 * 根据UserIdAndContactId删除
	 */
	@Override
	public Integer deleteUserContactByUserIdAndContactId(String userId, String contactId) {
		return this.userContactMapper.deleteByUserIdAndContactId(userId, contactId);
	}

	/**
	 * 搜索联系人
	 * @param userId 用户id
	 * @param contactId 联系人id
	 * @return
	 */
	@Override
	public UserContactSearchResultDTO search(String userId, String contactId) {
		//根据联系人id前缀判断联系人类型：好友/群
		UserTypeEnum userTypeEnum = UserTypeEnum.getByPrefix(contactId);
		if (userTypeEnum == null) {
			return null;
		}
		UserContactSearchResultDTO searchResultDTO = new UserContactSearchResultDTO();
		switch (userTypeEnum) {
			//搜用户
			case USER:
				UserInfo userInfo = userInfoMapper.selectByUserId(contactId);
				if (userInfo == null) {
					return null;
				}
				//好友类联系人的特有字段
				searchResultDTO.setSex(userInfo.getSex());
				searchResultDTO.setAreaName(userInfo.getAreaName());
				searchResultDTO.setNickName(userInfo.getNickName());
				break;
				//搜群聊
			case GROUP:
				GroupInfo groupInfo = groupInfoMapper.selectByGroupId(contactId);
				if (groupInfo == null) {
					return null;
				}
				//群组类联系人的特有字段
				searchResultDTO.setNickName(groupInfo.getGroupName());
				break;
		}
		//两类联系人的公有字段
		searchResultDTO.setContactId(contactId);
		searchResultDTO.setContactType(userTypeEnum.toString());
		//特殊情况：自己搜索自己
		if (userId.equals(contactId)) {
			searchResultDTO.setStatus(UserContactStatusEnum.FRIEND.getStatus());
			return searchResultDTO;
		}
		//根据userId和contactId在联系人表中查询联系状态
		UserContact userContact = userContactMapper.selectByUserIdAndContactId(userId, contactId);
		//根据查询出的联系状态进行设置
		searchResultDTO.setStatus(userContact == null ? UserContactStatusEnum.FRIEND_NO.getStatus() : userContact.getStatus());
		return searchResultDTO;
	}

	/**
	 * 申请加好友或者入群申请
	 * @param tokenUserInfoDTO 申请者信息
	 * @param contactId 联系人id
	 * @param applyInfo 申请信息
	 * @return joinType
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public Integer applyAdd(TokenUserInfoDTO tokenUserInfoDTO, String contactId, String applyInfo) {
		//获取联系人类型
		UserTypeEnum userTypeEnum = UserTypeEnum.getByPrefix(contactId);
		if (userTypeEnum == null) {
			throw new BusinessException(ResponseCodeEnum.CODE_600);
		}
		//申请人id
		String applyUserId = tokenUserInfoDTO.getUserId();
		//如果未传入申请信息，则设置为默认申请信息
		if (StringTools.isEmpty(applyInfo)) {
			applyInfo = String.format(Constants.APPLY_INFO_TEMPLATE, tokenUserInfoDTO.getNickName());
		}
		//返回值
		Integer joinType = null;
		//接收人id ：申请加好友时，接收人id就是contactId，申请加群时，接收人id是群主id
		String receiveUserId = null;
		//查询联系状态
		UserContact userContact = userContactMapper.selectByUserIdAndContactId(applyUserId, contactId);
		//如果被拉黑则无法添加
		if (userContact != null && (userContact.getStatus().equals(UserContactStatusEnum.BLACKLIST_BY_FIRST.getStatus()) || userContact.getStatus().equals(UserContactStatusEnum.BLACKLIST_BY.getStatus()))) {
			throw new BusinessException("对方已将你拉黑，无法添加好友");
		}
		//两种情况：好友 群组
		switch (userTypeEnum) {
			case GROUP:
				GroupInfo groupInfo = groupInfoMapper.selectByGroupId(contactId);
				if (groupInfo == null || groupInfo.getStatus().equals(GroupStatusEnum.DISBAND.getStatus())) {
					throw new BusinessException("群组不存在或已解散");
				}
				//申请加群时，接收人id是群主id
				receiveUserId = groupInfo.getGroupOwnerId();
				//加入类型(直接加/同意后加)
				joinType = groupInfo.getJoinType();
				break;
			case USER:
				UserInfo userInfo = userInfoMapper.selectByUserId(contactId);
				if (userInfo == null) {
					//通过easychat界面加好友时，contactId一定能搜到，如果查询结果为null，抛出异常
					throw new BusinessException(ResponseCodeEnum.CODE_600);
				}
				joinType = userInfo.getJoinType();
				receiveUserId = contactId;
				break;
		}
		//无需审核直接加入，则不用记录申请记录
		if (joinType.equals(JoinTypeEnum.ALLOW.getType())) {
			//添加信息到联系人表
			UserContactApply userContactApply = new UserContactApply();
			userContactApply.setApplyUserId(applyUserId);
			userContactApply.setContactId(contactId);
			userContactApply.setContactType(userTypeEnum.getType());
			userContactApplyService.addContact(userContactApply);
			return joinType;
		}
		//需要审核，向user_contact_apply表插入申请记录
		UserContactApply dbUserContactApply = userContactApplyMapper.selectByApplyUserIdAndReceiveUserIdAndContactId(applyUserId, receiveUserId, contactId);
		if (dbUserContactApply == null) {
			//数据库中还没有申请记录，则添加申请记录
			UserContactApply userContactApply = new UserContactApply();
			userContactApply.setApplyUserId(applyUserId);
			userContactApply.setReceiveUserId(receiveUserId);
			userContactApply.setContactId(contactId);
			userContactApply.setContactType(userTypeEnum.getType());
			userContactApply.setApplyInfo(applyInfo);
			userContactApply.setStatus(UserContactApplyStatusEnum.PENDING.getStatus());
			userContactApply.setLastApplyTime(System.currentTimeMillis());
			userContactApplyMapper.insert(userContactApply);
		} else {
			//数据库中已有申请记录，则更新状态: last_apply_time apply_info status
			UserContactApply userContactApply = new UserContactApply();
			userContactApply.setStatus(UserContactApplyStatusEnum.PENDING.getStatus());
			userContactApply.setApplyInfo(applyInfo);
			userContactApply.setLastApplyTime(System.currentTimeMillis());
			userContactApplyMapper.updateByApplyId(userContactApply, dbUserContactApply.getApplyId());
		}
		//发送加好友提醒：当数据库中还没有申请记录，或者申请状态不是待处理时才发送提醒
		if (dbUserContactApply == null || !dbUserContactApply.getStatus().equals(UserContactApplyStatusEnum.PENDING.getStatus())) {
			//发送ws消息
			MessageSendDTO messageSendDTO = new MessageSendDTO();
			messageSendDTO.setMessageType(MessageTypeEnum.CONTACT_APPLY.getType());
			messageSendDTO.setMessageContent(applyInfo);
			messageSendDTO.setContactId(receiveUserId);
			messageHandler.sendMessage(messageSendDTO);
		}
		return joinType;
	}

//	/**
//	 * 添加联系人
//	 * @param userContactApply
//	 */
//	@Override
//	public void addContact(UserContactApply userContactApply) {
//		//申请加群组的情况
//		if (UserTypeEnum.GROUP.getType().equals(userContactApply.getContactType())) {
//			//看群人数是否超出限制
//			UserContactQuery userContactQuery = new UserContactQuery();
//			userContactQuery.setContactId(userContactApply.getContactId());//指定群ID
//			userContactQuery.setStatus(UserContactStatusEnum.FRIEND.getStatus());//指定状态为好友
//			Integer groupMembers = userContactMapper.selectCount(userContactQuery);
//			SysSettingDTO sysSetting = redisComponent.getSysSetting();
//			if (groupMembers >= sysSetting.getMaxGroupMemberCount()) {
//				throw new BusinessException("群人数超出限制，最大人数为" + sysSetting.getMaxGroupMemberCount());
//			}
//		}
//		//双方添加好友：如果是人+人，需要向user_contact表添加两条数据，user_id和contact_id相反
//		//如果是人+群，只需要向user_contact表添加一条数据
//		Date curDate = new Date();
//		List<UserContact> userContactList = new ArrayList<>();
//		UserContact userContact = new UserContact();
//		userContact.setUserId(userContactApply.getApplyUserId());
//		userContact.setContactId(userContactApply.getContactId());
//		userContact.setContactType(userContactApply.getContactType());
//		userContact.setStatus(UserContactStatusEnum.FRIEND.getStatus());
//		userContact.setCreateTime(curDate);
//		userContact.setLastUpdateTime(curDate);
//		userContactList.add(userContact);
//		if (UserTypeEnum.USER.getType().equals(userContactApply.getContactType())) {
//			//人+人
//			UserContact userContact2 = new UserContact();
//			userContact2.setUserId(userContactApply.getReceiveUserId());
//			userContact2.setContactId(userContactApply.getApplyUserId());
//			userContact2.setContactType(userContactApply.getContactType());
//			userContact2.setStatus(UserContactStatusEnum.FRIEND.getStatus());
//			userContact2.setCreateTime(curDate);
//			userContact2.setLastUpdateTime(curDate);
//			userContactList.add(userContact2);
//		}
//		//批量插入
//		userContactMapper.insertOrUpdateBatch(userContactList);
//	}

	/**
	 * 删除或拉黑联系人(需要修改两条记录，自己和好友的关系，好友和自己的关系)
	 * @param userId
	 * @param contactId
	 * @param userContactStatusEnum
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void removeUserContact(String userId, String contactId, UserContactStatusEnum userContactStatusEnum) {
		Date curDate = new Date();
		UserContact userContact = new UserContact();
		userContact.setStatus(userContactStatusEnum.getStatus());
		userContact.setLastUpdateTime(curDate);
		//删除联系人只是改变了联系人状态，并没有从数据库直接删除记录
		userContactMapper.updateByUserIdAndContactId(userContact, userId, contactId);
		//修改好友的联系人信息
		UserContact friendContact = new UserContact();
		if (userContactStatusEnum == UserContactStatusEnum.DELETE) {
			friendContact.setStatus(UserContactStatusEnum.DELETE_BY.getStatus());
		} else if (userContactStatusEnum == UserContactStatusEnum.BLACKLIST) {
			friendContact.setStatus(UserContactStatusEnum.BLACKLIST_BY.getStatus());
		}
		friendContact.setLastUpdateTime(curDate);
		userContactMapper.updateByUserIdAndContactId(friendContact, contactId, userId);
		//TODO 从我的好友列表缓存中删除好友
		redisComponent.removeUserContact(userId, contactId);
		//TODO 从好友的好友列表缓存中删除我
		redisComponent.removeUserContact(contactId, userId);
	}

	/**
	 * 添加机器人好友
	 * @param userId 要添加机器人好友的用户id
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void addContact4Robot(String userId) {
		Date curDate = new Date();
		SysSettingDTO sysSetting = redisComponent.getSysSetting();
		String contactId = sysSetting.getRobotUid();
		String contactName = sysSetting.getRobotNickName();
		String sendMessage = sysSetting.getRobotWelcome();
		sendMessage = StringTools.cleanHtmlTag(sendMessage);//防止html注入
		//添加机器人为好友
		UserContact userContact = new UserContact();
		userContact.setUserId(userId);
		userContact.setContactId(contactId);
		userContact.setContactType(UserTypeEnum.USER.getType());
		userContact.setStatus(UserContactStatusEnum.FRIEND.getStatus());
		userContact.setCreateTime(curDate);
		userContact.setLastUpdateTime(curDate);
		userContactMapper.insert(userContact);
		//增加会话信息 chat_session表
		String sessionId = StringTools.getChatSessionId4User(new String[]{userId, contactId});
		ChatSession chatSession = new ChatSession();
		chatSession.setSessionId(sessionId);
		chatSession.setLastMessage(sendMessage);
		chatSession.setLastReceiveTime(curDate.getTime());
		chatSessionMapper.insert(chatSession);
		//增加会话人信息 chat_session_user表
		ChatSessionUser chatSessionUser = new ChatSessionUser();
		chatSessionUser.setUserId(userId);
		chatSessionUser.setContactId(contactId);
		chatSessionUser.setContactName(contactName);
		chatSessionUser.setSessionId(sessionId);
		chatSessionUserMapper.insert(chatSessionUser);
		//增加聊天消息 chat_message表
		ChatMessage chatMessage = new ChatMessage();
		chatMessage.setSessionId(sessionId);
		chatMessage.setMessageType(MessageTypeEnum.CHAT.getType());
		chatMessage.setMessageContent(sendMessage);
		chatMessage.setSendUserId(contactId);//发送人：机器人
		chatMessage.setSendUserNickName(contactName);
		chatMessage.setSendTime(curDate.getTime());
		chatMessage.setContactId(userId);//接收人：登录的用户
		chatMessage.setContactType(UserTypeEnum.USER.getType());
		chatMessage.setStatus(MessageStatusEnum.COMPLETED.getStatus());//非文件类型消息，默认发送完成
		chatMessageMapper.insert(chatMessage);
	}
}